package com.letu.core.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.letu.annotation.annotation.LanguageConvert.LanguageEntityConvert;
import com.letu.annotation.base.LanguageTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 集合内容类型转换
 *
 * @ClassName Test
 * @Description TODO
 * @Author liuxiaobai
 * @Date 2021/8/25 3:52 下午
 * @Version 1.0
 */
@Slf4j
public class ConvertUtil {

    /**
     * list内容转换
     *
     * @param source 源
     * @param clazz  目标类型
     * @return 转换后的结果集合
     */
    public static <E, V> List<V> convertList(List<E> source, Class<V> clazz) {
        if (source == null || source.isEmpty()) {
            return Collections.emptyList();
        }
        List<V> result = new ArrayList<>(source.size());
        source.forEach(e -> {
            V obj = BeanUtil.copyProperties(e, clazz);
            result.add(obj);
        });
        return result;
    }

    /**
     * page内容转换
     *
     * @param source - 源
     * @param clazz  目标类型
     * @return 转换后的结果page
     */
    public static <E, V> Page<V> convertPage(Page<E> source, Class<V> clazz) {
        Page<V> result = new Page<>();
        //转换分页相关属性 忽略records内容
        BeanUtil.copyProperties(source, result, "records");
        result.setRecords(convertList(source.getRecords(), clazz));
        return result;
    }


    /**
     * page内容转换
     *
     * @param source - 源
     * @param clazz  目标类型
     * @return 转换后的结果page
     */
    public static <E, V> IPage<V> convertIPage(IPage<E> source, Class<V> clazz) {
        IPage<V> result = new Page<>();
        //转换分页相关属性 忽略records内容
        BeanUtil.copyProperties(source, result, "records");
        result.setRecords(convertList(source.getRecords(), clazz));
        return result;
    }


    /**
     * page内容转换
     *
     * @param source - 源
     * @param vList  目标list
     * @return 转换后的结果page
     */
    public static <E, V> Page<V> convertPage(Page<E> source, List<V> vList) {
        Page<V> result = new Page<>();
        //转换分页相关属性 忽略records内容
        BeanUtil.copyProperties(source, result, "records");
        result.setRecords(vList);
        return result;
    }


    /**
     * page内容转换
     *
     * @param source - 源
     * @param vList  目标list
     * @return 转换后的结果page
     */
    public static <E, V> IPage<V> convertIPage(IPage<E> source, List<V> vList) {
        IPage<V> result = new Page<>();
        //转换分页相关属性 忽略records内容
        BeanUtil.copyProperties(source, result, "records");
        result.setRecords(vList);
        return result;
    }

    /**
     * 国际化语言翻译
     *
     * @param data           数据
     * @param languageType   语言
     * @param convertPrimary true 将子字段转至主字段去，其他的进行补全
     * @return
     */
    public static Object convertByLanguageType(Object data, LanguageTypeEnum languageType, boolean convertPrimary) {

        Object convertData = data;

        if (Page.class.getName().equals(data.getClass().getName())) {
            convertData = ((Page) data).getRecords();
        }

        if (Objects.isNull(convertData)) {
            return null;
        }

        if (Collection.class.isAssignableFrom(convertData.getClass())) {
            Collection collection = (Collection) convertData;
            Iterator<Object> iterator = collection.iterator();
            Object o;
            while (iterator.hasNext()) {
                o = iterator.next();
                convert(o, languageType, convertPrimary);
            }
            return data;
        } else if (Map.class.isAssignableFrom(convertData.getClass())) {
            log.error("不支持MAP类型国际化");
            return data;
        } else if (convertData.getClass().isAnnotationPresent(LanguageEntityConvert.class)) {
            convert(data, languageType, convertPrimary);
        }
        return data;
    }

    private static void convert(Object data, LanguageTypeEnum languageType, boolean convertPrimary) {
        if (convertPrimary) {
            EntityLanguageFieldConvertUtils.convertPrimary(data, languageType);
        } else {
            EntityLanguageFieldConvertUtils.convert(data, languageType);
        }
    }

}
